#ifndef GNASH_UTILS_H
#define GNASH_UTILS_H

//{{{
#include <Ogre.h>
#include <OIS.h>

//#include <backend/Renderer.h>
//#include <backend/Renderer_agg.h>
#include <librender/Renderer.h>
#include <librender/Renderer_agg.h>
#include <GnashKey.h>
#include <gnash.h>
#include <DisplayObject.h>
#include <DisplayObjectContainer.h>
#include <MovieClip.h>
#include <MovieFactory.h>
#include <movie_root.h>
#include "smart_ptr.h"
#include "libbase/IOChannel.h"
#include "utility.h"
#include "log.h"
#include "libcore/parser/SWFMovieDefinition.h"
#include "libcore/parser/BitmapMovieDefinition.h"
#include "RunResources.h"
#include "URL.h"
#include "StreamProvider.h"
#include "MovieLibrary.h"
#include "movie_definition.h"
#include "libcore/asobj/Global_as.h"
#include "libcore/swf/TagLoadersTable.h"
#include "libcore/swf/DefaultTagLoaders.h"
#include "libbase/noseek_fd_adapter.h"
#include "SWFRect.h"
#include "VM.h"
#include "ManualClock.h"
#include "VirtualClock.h"
#include "libcore/SystemClock.h"
#include "as_environment.h"
#include "as_value.h"
#include "as_object.h"
#include "as_function.h"
#include "Array_as.h"
#include <fn_call.h>
#include "string_table.h"
#include "builtin_function.h"
#include "drag_state.h"
#include "GnashException.h"
#include "vm/ExecutableCode.h"
#include "namedStrings.h"
#include "GnashNumeric.h"

#include "boost/tuple/tuple.hpp"
//}}}

using namespace std;
using namespace gnash;

namespace Reflect
	{

	/**
	* @param f Field name
	* @param o Object
	* @return as_value Field's value
	*/
	static const as_value field(const std::string& f, as_object *o)
	{
		return o->getMember(getStringTable(*o).find(f));
	}

	template <typename T >
	static as_value callMethod(as_object* o, const std::string& f, const T& arg)
	{
		as_value v = field(f, o);
		if (v.is_null() || v.is_undefined() || !v.is_function()) return as_value();

		as_environment env(VM::get());
		fn_call fnc(o, env);

		fnc.pushArg(arg);

		as_function* func = v.to_function();
		return func->call(fnc);
	}


//    /**
//    * @param o Object
//    * @param f Method (field) name
//    * @param args Arguments object
//    * @return as_value Method's return value
//    */
//    static as_value callMethod(as_object* o, const std::string& f, luabind::adl::object args) {
//
//        as_value v = field(f, o);
//        if(v.is_null() || v.is_undefined() || !v.is_function()) return as_value();
//
//        as_environment env(VM::get());
//        fn_call fnc(o, env);
//
////        lua_State* L = args.interpreter();
//
//        if (type(args) == LUA_TTABLE)
//	    for (luabind::iterator i(args), end; i != end; ++i)
//        {
//
//        const object &keyObj = i.key();
//        string key = object_cast<string>(keyObj);
////        cout << key << "[" << lua_typename(L, type(*i)) << "]=" << (*i) << endl;
////            (*i).push(L);
//            switch(type(*i))
//            {
//                case LUA_TBOOLEAN:
////                    fnc.pushArg(lua_toboolean(L, -1));
//                    fnc.pushArg(object_cast<bool>(*i));
//                break;
//                case LUA_TNUMBER:
//                    fnc.pushArg(object_cast<float>(*i));
//                break;
//                case LUA_TSTRING:
//                    fnc.pushArg(object_cast<string>(*i));
//                break;
//            }
////            lua_pop(L, 1);
//        }
//        else
//        switch(type(args))
//        {
//            case LUA_TBOOLEAN:
//                fnc.pushArg(object_cast<bool>(args));
//            break;
//            case LUA_TNUMBER:
//                fnc.pushArg(object_cast<float>(args));
//            break;
//            case LUA_TSTRING:
//                fnc.pushArg(object_cast<string>(args));
//            break;
//        }
//
////        cout << o->stringValue() << "." << f << "(" << fnc.dump_args() << ")" << endl;
//
//        as_function* func = v.to_function();
//        return func->call(fnc);
//    }
}

class GnashUtils
	{
	public:

		static void clearTexture(Ogre::Texture* tex);
		static void blit(unsigned char* bmp, Ogre::Texture* tex);
		static gnash::key::code getGnashKey(OIS::KeyCode e);

		static as_value onLoadCallBack(const fn_call& f);
	};

#endif // GNASH_UTILS_H
